/**
 *
 * Copyright (c) 2014 BinKylin Studio.
 *
 * Author: TBinkylin
 * Created Date: 2014-03-01
 * 
 * 	version					author					remark
 * 	1.0						benoit				
 */
package net.binkylin.common.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import net.binkylin.common.constant.CommConstants;

import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PropertyUtil {

	private static final Logger log = LoggerFactory.getLogger(DatabaseUtil.class);

	private static Map<String, Object> table = new WeakHashMap<String, Object>();
	private static long reloadPeriod = 5000;

	public PropertyUtil() {
	}

	/**
	 * @throws Exception
	 * 
	 * @Description get property by key with no exception
	 * @param propertyFileName
	 * @param key
	 * @throws Exception
	 * @return String
	 * @throws
	 */
	public static String getPropertyValueNoEx(String propertyFileName, String key) {
		try {
			return getPropertyValue(propertyFileName, key);
		} catch (Exception exception) {
			log.error("[MPA] error occurred: getPropertyValueNoEx", exception);
		}
		return "";
	}

	/**
	 * @throws Exception
	 * 
	 * @Description get property by key
	 * @param propertyFileName
	 * @param key
	 * @throws Exception
	 * @return String
	 * @throws
	 */
	public static String getPropertyValue(String propertyFileName, String key) throws Exception {
		String result = null;

		propertyFileName = getAbsolutePropertyFileName(propertyFileName);
		PropertiesConfiguration config = getConfig(propertyFileName);

		Object returnObj = config.getProperty(key);
		if (returnObj != null) {
			if (String.class.getName().equals(returnObj.getClass().getName())) {
				result = (String) returnObj;
			} else if (ArrayList.class.getName().equals(returnObj.getClass().getName())) {
				returnObj = ((ArrayList<?>) returnObj).get(0);
				if (String.class.getName().equals(returnObj.getClass().getName())) {
					result = (String) returnObj;
				}
			}
		}

		return result;
	}

	/**
	 * @throws Exception
	 * 
	 * @Description get property by key
	 * @param propertyFileName
	 * @param key
	 * @throws Exception
	 * @return String
	 * @throws
	 */
	public static String getList2String(String propertyFileName, String key) throws Exception {
		String result = null;
		propertyFileName = getAbsolutePropertyFileName(propertyFileName);

		PropertiesConfiguration config = getConfig(propertyFileName);
		Object returnObj = config.getProperty(key);

		if (returnObj != null) {
			if (String.class.getName().equals(returnObj.getClass().getName())) {
				result = (String) returnObj;
			} else if (ArrayList.class.getName().equals(returnObj.getClass().getName())) {
				@SuppressWarnings("unchecked")
				List<String> pList = (List<String>) returnObj;
				StringBuffer pbuff = new StringBuffer();
				for (int i = 0, j = pList.size(); i < j; i++) {
					pbuff.append(pList.get(i));
					if (i != j - 1)
						pbuff.append(",");
				}
				result = pbuff.toString();
			}
		}

		return result;
	}

	/**
	 * 
	 * @Description get properties by key,return a array(single key
	 *              corresponding multiple value)
	 * @param propertyFileName
	 * @param key
	 * @throws Exception
	 * @return String[]
	 * @throws
	 */
	public static String[] getPropertyValueArray(String propertyFileName, String key) throws Exception {
		if (StringUtils.isBlank(key))
			throw new Exception("Property key is blank!");

		String[] result = null;
		propertyFileName = getAbsolutePropertyFileName(propertyFileName);
		PropertiesConfiguration config = getConfig(propertyFileName);
		result = (String[]) config.getStringArray(key);

		return result;
	}

	/**
	 * 
	 * @Description get configuration of the specific file
	 * @param propertyFileName
	 * @throws Exception
	 * @return PropertiesConfiguration
	 * @throws
	 */
	private static PropertiesConfiguration getConfig(String propertyFileName) throws Exception {
		if (StringUtils.isBlank(propertyFileName))
			throw new Exception("propertyFileName is blank");

		PropertiesConfiguration config = (PropertiesConfiguration) table.get(propertyFileName);

		if (config == null) {
			config = new PropertiesConfiguration(propertyFileName);
			FileChangedReloadingStrategy fs = new FileChangedReloadingStrategy();
			fs.setRefreshDelay(reloadPeriod);
			config.setReloadingStrategy(fs);
			table.put(propertyFileName, config);
		}
		return config;

	}

	/**
	 * 
	 * @Description get configuration of the specific file
	 * @param propertyFileName
	 * @throws Exception
	 * @return PropertiesConfiguration
	 * @throws
	 */
	private static String getAbsolutePropertyFileName(String propertyFileName) throws Exception {

		// Properties prop = new Properties();
		String result = null;

		String defaultCfgFileName = System.getProperty(CommConstants.APP_DEFAULT_CONFIG);

		log.debug(defaultCfgFileName);

		PropertiesConfiguration config = getConfig(defaultCfgFileName);

		Object returnObj = config.getProperty(propertyFileName + CommConstants.APP_CONFIG_LOCATION);

		// if (returnObj==null) new
		// Exception("Property file location is not set!");
		if (returnObj == null) {
			log.warn("Property file location is not set, using original file name");
			return propertyFileName;
		}
		if (ArrayList.class.getName().equals(returnObj.getClass().getName())) {
			throw new Exception("More than two preperty files are defined!");
		}

		// Modified by lixg 10/Jun/2013
		log.debug("Before>>>>>>>>>return value class name:" + returnObj.getClass().getName());
		if (String.class.getName().equals(returnObj.getClass().getName())) {
			result = (String) returnObj;
			// result += "/";
			log.debug("After>>>>>>>>>return string type");
		}
		return result;

	}

	public static void main(String[] args) {
		try {
			log.debug(PropertyUtil.getPropertyValue("test.properties", "uncaughtable.exception"));
			log.debug(PropertyUtil.getPropertyValue("properties/test1.properties", "jms.def.cxf"));

		} catch (Exception e) {
			log.error("[MPA] error occurred: ", e);
		}

	}

}
